package org.takeback.chat.service;

import com.google.common.collect.ImmutableMap;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.takeback.chat.entity.GcLottery;
import org.takeback.chat.entity.GcLotteryDetail;
import org.takeback.chat.entity.PubUser;
import org.takeback.chat.lottery.Lottery;
import org.takeback.chat.lottery.LotteryDetail;
import org.takeback.chat.service.admin.SystemConfigService;
import org.takeback.service.BaseService;
import org.takeback.util.BeanUtils;

@Service("lotteryService")
public class LotteryService extends BaseService {
	@Transactional(rollbackFor = { Throwable.class })
	public int setLotteryExpired(String lotteryId) {
		return this.dao.executeUpdate("update GcLottery a set a.status = '2' where a.id = :id and a.status = '0'",
				ImmutableMap.of("id", lotteryId));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public int setLotteryFinished(String lotteryId) {
		return this.dao.executeUpdate("update GcLottery a set a.status = '1' where a.id = :id and a.status = '0'",
				ImmutableMap.of("id", lotteryId));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public int setRoomStatus(String roomId, String status) {
		return this.dao.executeUpdate("update GcRoom a set a.status =:status where a.id =:roomId",
				ImmutableMap.of("status", status, "roomId", roomId));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public int moneyDown(Integer uid, Double money) {
		return this.dao.executeUpdate(
				"update PubUser a set a.money = coalesce(a.money,0) - :money,a.exp=coalesce(exp,0)+:exp where a.id=:uid and a.money>=:money",
				ImmutableMap.of("money", money, "exp", money, "uid", uid));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public int moneyUp(Integer uid, Double money) {
		return this.dao.executeUpdate("update PubUser a set a.money = coalesce(a.money,0) + :money where a.id=:uid ",
				ImmutableMap.of("money", money, "uid", uid));
	}
	

	@Transactional
	public int userUaterUp(Integer userId, Double money) {
		return this.dao.executeUpdate(
				"update PubUser a set a.water = coalesce(a.water,0) + :money where a.id=:uid",
				ImmutableMap.of("money", money, "uid", userId));
	}


	@Transactional(rollbackFor = { Throwable.class })
	public int waterDown(String roomId, Double money) {
		return this.dao.executeUpdate(
				"update GcRoom a set a.sumFee = coalesce(a.sumFee,0) - :money where a.id=:roomId ",
				ImmutableMap.of("money", money, "roomId", roomId));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public int waterUp(String roomId, Double money) {
		return this.dao.executeUpdate(
				"update GcRoom a set a.sumFee = coalesce(a.sumFee,0) + :money,a.sumPack = coalesce(a.sumPack,0)+1 where a.id=:roomId ",
				ImmutableMap.of("money", money, "roomId", roomId));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public void saveLotteryDetail(Lottery lottery, LotteryDetail detail) {
		GcLotteryDetail gcLotteryDetail = (GcLotteryDetail) BeanUtils.map(detail, GcLotteryDetail.class);
		gcLotteryDetail.setLotteryid(lottery.getId());
		gcLotteryDetail.setLotteryid(lottery.getId());
		this.dao.save(GcLotteryDetail.class, gcLotteryDetail);
		BigDecimal money = detail.getCoin();
		this.dao.executeUpdate("update PubUser set money=money+:money where id = :uid",
				ImmutableMap.of("money", Double.valueOf(money.doubleValue()), "uid", detail.getUid()));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public BigDecimal giftLotteryExpired(Lottery lottery) {
		Integer sender = lottery.getSender();
		if (sender.intValue() <= 0) {
			return null;
		}
		Map<Integer, LotteryDetail> dts = lottery.getDetail();
		Collection<LotteryDetail> c = dts.values();
		BigDecimal bd = lottery.getMoney();
		Iterator<LotteryDetail> itr = c.iterator();
		while (itr.hasNext()) {
			LotteryDetail ld = (LotteryDetail) itr.next();
			bd = bd.subtract(ld.getCoin());
		}
		this.dao.executeUpdate("update PubUser a set a.money =coalesce(a.money,0) + :rest where a.id = :uid ",
				ImmutableMap.of("rest", Double.valueOf(bd.doubleValue()), "uid", sender));
		this.dao.executeUpdate("update GcLottery a set a.status = '2' where a.id = :id and a.status = '0'",
				ImmutableMap.of("id", lottery.getId()));
		return bd;
	}

	@Transactional(rollbackFor = { Throwable.class })
    public void changeMoney(final Map<Integer, Double> data) {
        for (final Integer uid : data.keySet()) {
            final Double v = data.get(uid);
            this.dao.executeUpdate("update PubUser a set a.money =coalesce(a.money,0) + :money where a.id = :uid ", (Map<String, Object>)ImmutableMap.of("money", v, "uid", (Object)uid));
        }
    }
    
	@Transactional(rollbackFor = { Throwable.class })
	public void createLottery(Lottery lottery, double deposit) {
		Integer uid = lottery.getSender();
		GcLottery gcLottery = (GcLottery) BeanUtils.map(lottery, GcLottery.class);
		this.dao.save(GcLottery.class, gcLottery);
		moneyDown(uid, Double.valueOf(deposit));
	}

	@Transactional(rollbackFor = { Throwable.class })
	public Lottery loadLottery(String lotteryId) {
		GcLottery gcLottery = (GcLottery) this.dao.get(GcLottery.class, lotteryId);
		if (gcLottery == null) {
			return null;
		}
		Lottery lottery = (Lottery) BeanUtils.map(gcLottery, Lottery.class);
		List<GcLotteryDetail> detailList = this.dao.findByProperty(GcLotteryDetail.class, "lotteryId", lotteryId);
		for (GcLotteryDetail gld : detailList) {
			LotteryDetail detail = (LotteryDetail) BeanUtils.map(gld, LotteryDetail.class);
			lottery.addDetail(detail);
		}
		lottery.setStatus(gcLottery.getStatus());
		return lottery;
	}

	@Transactional(rollbackFor = { Throwable.class })
	public List<GcLottery> loadRecentLottery(String roomId) {
		List<GcLottery> lotteries = this.dao.findByHqlPaging(
				"from GcLottery where  roomId =:roomId and status<>0 order by id desc",
				ImmutableMap.of("roomId", roomId), 10, 1);
		return lotteries;
	}

	@Transactional
	public void test() {
		List<Double> l = this.dao.findByHql("select sum(money)+(select sum(sumFee) from GcRoom ) from PubUser");
		System.out.println("站内总金额:" + l.get(0));
	}

	@Transactional
	public void setBackWater(Integer uid, Double water) {
		if (water.doubleValue() <= 0.0D) {
			return;
		}
		PubUser u = (PubUser) this.dao.get(PubUser.class, uid);
		if ((u.getParent() == null) || (u.getParent().intValue() <= 0)) {
			return;
		}
		for (int i = 1; i <= 3; i++) {
			PubUser parent = (PubUser) this.dao.get(PubUser.class, u.getParent());
			if (parent == null) {
				return;
			}
			Double rate = Double.valueOf(SystemConfigService.getValue("w_" + i));
			this.dao.executeUpdate("update PubUser a set a.money =coalesce(a.money,0) + :money where a.id = :uid ",
					ImmutableMap.of("money", Double.valueOf(water.doubleValue() * rate.doubleValue()), "uid",
							parent.getId()));
			if ((parent.getParent() == null) || (parent.getParent().intValue() <= 0)) {
				return;
			}
			u = parent;
		}
	}
}
